package com.tianxinweb.controller;


import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.plugins.Page;
import com.tianxinweb.entity.*;
import com.tianxinweb.enums.ResultEnum;
import com.tianxinweb.exception.MyException;
import com.tianxinweb.service.AdminService;
import com.tianxinweb.service.PrivilegeService;
import com.tianxinweb.service.RoleService;
import com.tianxinweb.utils.IdGen;
import com.tianxinweb.utils.IpUtil;
import com.tianxinweb.utils.Md5Util;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import javax.validation.Valid;
import java.util.*;

/**
 * <p>
 *  前端控制器
 * </p>
 *
 * @author cboy
 * @since 2018-07-19
 */
@RestController
@RequestMapping("/admin")
public class AdminController {

    @Autowired
    private AdminService adminService;

    @Autowired
    private PrivilegeService privilegeService;

    @Autowired
    private RoleService roleService;

    /**
     * 管理员登录
     * @param admin
     * @param result
     * @param request
     * @return
     */
    @PostMapping("login")
    public Result login(@RequestBody @Valid Admin admin, BindingResult result,HttpSession session,
                        HttpServletRequest request) {
        if(result.hasErrors()){//账号或密码不正确
            throw new MyException(ResultEnum.LOGIN_PWD_OR_ACCOUNT_ERROR);
        }
        Admin adminInfo = adminService.getAdminByName(admin.getAdminName());
        if(adminInfo==null) throw new MyException(ResultEnum.LOGIN_PWD_OR_ACCOUNT_ERROR);

        String md5Pwd = Md5Util.generate(admin.getAdminPwd(), adminInfo.getPwdSalt());
        if(!adminInfo.getAdminPwd().equals(md5Pwd)) throw new MyException(ResultEnum.LOGIN_PWD_OR_ACCOUNT_ERROR);//账号或密码不正确

        if(adminInfo.getAdminStatus()) throw new MyException(ResultEnum.ACCOUNT_LOCKED_UP);//账号已被禁用
        adminInfo.setLastLoginIp(IpUtil.getIp(request));
        adminInfo.setLastLoginTime(new Date());
        adminInfo.setLoginCount(adminInfo.getLoginCount()+1);
        //保存登录信息
        adminService.updateById(adminInfo);
        //如果不为admin则获取该管理员的权限
        if(!"admin".equals(adminInfo.getAdminName())){
            String jsonIds = adminInfo.getRoleIds();
            Set<Integer> privIds = new HashSet<>();//该管理员拥有的所有权限id
            if(jsonIds != null && !"".equals(jsonIds)){
                Set<Integer> idList = JSON.parseObject(jsonIds,Set.class);
                //获取管理员的角色
                List<Role> roleList = roleService.selectBatchIds(idList);
                for(Role role : roleList){
                    String pidsJson =  role.getPriviIds();
                    if(pidsJson != null){
                        privIds.addAll(JSON.parseObject(pidsJson,Set.class));
                    }
                }
            }

            String privsJson = adminInfo.getPrivIds();
            if(privsJson!=null && !"".equals(privsJson)){
                privIds.addAll(JSON.parseObject(jsonIds,List.class));
            }


            //获取该管理员所有权限并保存在session中
            if(privIds.isEmpty()){
                session.setAttribute("privilege", Collections.EMPTY_LIST);
            }else{
                List<Privilege> list = privilegeService.selectBatchIds(privIds);
                session.setAttribute("privilege", list);
            }
        }

        session.setAttribute("adminId", adminInfo.getAdminId());
        session.setAttribute("adminName", adminInfo.getAdminName());
        return Result.success();
    }

    /**
     * 注销登录
     * @param session
     * @return
     */
    @RequestMapping("logout")
    public Result logout(HttpSession session) {
        session.removeAttribute("adminId");
        session.removeAttribute("adminName");
        session.removeAttribute("privilege");
        return Result.success();
    }

    /**
     * 获取/搜索管理员列表
     * 分页每页默认显示10条
     * @param pn
     * @param size
     * @return
     */
    @RequestMapping("list")
    public Result list(@RequestParam(value="pn",defaultValue="1") Integer pn,
                       @RequestParam(value="size",defaultValue="10") Integer size,
                       @RequestParam(value = "key",defaultValue = "") String key) {
        Page<Admin> page = adminService.getAdminList(pn,size,key);
        return Result.success().add("page", page);
    }

    /**
     * 通过管理员id获取管理员角色
     * @param id 管理员id
     * @return
     */
    @RequestMapping("getAdminRoleById/{id}")
    public Result getAdminRoleById(@PathVariable("id") Integer id){
        Admin admin  = adminService.selectById(id);
        if(admin != null && admin.getRoleIds() != null){
            List<Integer> ids = roleService.selectBatchIds(JSON.parseObject(admin.getRoleIds(), List.class));
            return Result.success().add("roles",ids);
        }
        return Result.success().add("roles",Collections.EMPTY_LIST);
    }

    /**
     * 通过管理员id获取管理员不在角色中的权限id，即acl权限
     * @param id 管理员id
     * @return
     */
    @RequestMapping("getAdminPrivById/{id}")
    public Result getAdminPrivById(@PathVariable("id") Integer id){
        Admin admin  = adminService.selectById(id);
        if(admin != null && admin.getPrivIds() != null){
            List<Integer> privs = JSON.parseObject(admin.getPrivIds(), List.class);
            return Result.success().add("ids",privs);
        }
        return Result.success().add("ids",Collections.EMPTY_LIST);
    }

    /**
     * 更新管理员的acl权限
     * @param aid
     * @param pids
     * @return
     */
    @PostMapping("updateAdminPrivByid")
    public Result updateAdminPrivByid(@RequestParam("aid") Integer aid,@RequestParam("pids") String pids){
        Admin admin  = adminService.selectById(aid);
        if(admin==null) return Result.fail();
        adminService.updateAdminPriv(admin,pids);
        return Result.success();
    }

    /**
     * 检查管理员账号的唯一性
     * @return
     */
    @RequestMapping("checkAdminNameUnique")
    public Result checkAdminNameUnique(@RequestParam("adminName") String adminName) {

        boolean b = false;
        if(adminName.length()>3){
            b = adminService.getAdminByName(adminName)==null?true:false;
        }
        return b?Result.success():Result.fail();
    }

    /**
     * 添加管理员
     * @param admin
     * @param reuslt
     * @return
     */
    @PostMapping("add")
    public Result add(@RequestBody @Valid Admin admin,BindingResult reuslt){
        if(reuslt.hasErrors()){
            throw new MyException(ResultEnum.PARAMETER_FORMAT_ERROR);//参数格式不正确
        }
        if(!admin.validatePwd()) throw new MyException(ResultEnum.COMFIRM_PWD_ERROR);//确认密码不正确

        Admin dbAdmin = adminService.getAdminByName(admin.getAdminName());
        if(dbAdmin != null) throw new MyException(ResultEnum.ADMIN_NAME_USED);

        adminService.addAdmin(admin);
        return Result.success();
    }

    /**
     * 根据id删除管理员
     * @return
     */
    @RequestMapping("delete/{id}")
    public Result delete(@PathVariable("id") Integer id,@RequestParam(value = "type",defaultValue = "1") Integer type){
        Admin admin = new Admin();
        admin.setAdminId(id);
        if(type==1){
            admin.setAdminStatus(true);
        }else{
            admin.setAdminStatus(false);
        }
        adminService.updateById(admin);
        return Result.success();
    }

    /**
     * 超级管理员修改管理员密码
     * @param vo
     * @param result
     * @return
     */
    @PostMapping("adminEditPwd")
    public Result restPwd(@RequestBody @Valid AdminEditPwdVo vo, BindingResult result, HttpSession session){
        if(result.hasErrors()) throw new MyException(ResultEnum.PARAMETER_FORMAT_ERROR);
        if(!vo.valid()) throw new MyException(ResultEnum.COMFIRM_PWD_ERROR);

        Integer adminId = (Integer) session.getAttribute("adminId");
        Admin loginAdmin = adminService.selectById(adminId);
        String loginAdminMd5 = Md5Util.generate(vo.getAdminPwd(),loginAdmin.getPwdSalt());
        if(!loginAdminMd5.equals(loginAdmin.getAdminPwd())){
            throw new MyException(ResultEnum.ADMIN_WORKINGPWD_ERROR);
        }
        Admin admin = adminService.selectById(vo.getId());
        String salt = IdGen.getRandomString(16);
        admin.setAdminPwd(Md5Util.generate(vo.getNewPwd(),salt));
        admin.setPwdSalt(salt);
        adminService.updateById(admin);
        return Result.success();
    }

    /**
     * 管理员修改自身密码
     * @param vo
     * @param result
     * @param session
     * @return
     */
    @PostMapping("editPwd")
    public Result editPwd(@RequestBody @Valid EditPwdVo vo,BindingResult result,HttpSession session){
        if(result.hasErrors() || !vo.valid() ) throw new MyException(ResultEnum.PARAMETER_FORMAT_ERROR);
        if(!vo.valid()) throw new MyException(ResultEnum.COMFIRM_PWD_ERROR);
        Integer adminId = (Integer) session.getAttribute("adminId");
        Admin admin = adminService.selectById(adminId);
        if(!admin.getAdminPwd().equals(Md5Util.generate(vo.getOldPwd(),admin.getPwdSalt()))){
            throw new MyException(ResultEnum.OLDPWD_ERROR);
        }
        String salt = IdGen.getRandomString(16);
        admin.setAdminPwd(Md5Util.generate(vo.getNewPwd(),salt));
        admin.setPwdSalt(salt);
        adminService.updateById(admin);
        return Result.success();
    }

    /**
     * 更改管理员角色
     * @return
     */
    @RequestMapping("update/{id}")
    public Result update(@PathVariable("id") Integer id, @RequestParam("roleIds") String ids){
        Admin admin = adminService.selectById(id);
        if(admin==null) throw new MyException(ResultEnum.FAILE);
        adminService.updateAdminRole(admin,ids);
        return Result.success();

    }

    /**
     * 获取管理员需显示的菜单
     * @param session
     * @return map key格式：privs_+level,例如：privs_0
     */
    @RequestMapping("getAdminMenu")
    public Result getAdminMenu(HttpSession session){
        String adminName = (String) session.getAttribute("adminName");

        int level = privilegeService.getMenuLevel();
        Map<String,List<Privilege>> map = new HashMap<>();
        if("admin".equals(adminName)){//如果是admin则获取所有权限
            for(int i=0;i<=level;i++){
                map.put("priv_"+i,privilegeService.getMenuByLevel(i));
            }
        }else{
            List<Privilege> privileges = (List<Privilege>) session.getAttribute("privilege");
            List<Integer> idList = new ArrayList<>();
            if(privileges != null){
                int level2 = -1;
                for(Privilege priv : privileges){
                    int pLevel = priv.getPrivLevel();
                    if(priv.getMenuStatus() && priv.getShowStatus()){
                        if(pLevel>level2){
                            level2 = pLevel;//获取菜单层级
                        }
                        idList.add(priv.getPid());//获取管理员所有权限id
                    }
                }
                level = level2;
                for(int i=0;i<=level2;i++){
                    map.put("priv_"+i,privilegeService.getManagerMenuByLevel(i,idList));
                }
            }
        }

        return Result.success().add("level",level).add("privs", map);
    }

    /**
     * 获取管理员名称
     * @return
     */
    @RequestMapping("getAdminName")
    public Result getAdminName(HttpSession session){
        String adminName = (String) session.getAttribute("adminName");
        return Result.success().add("name", adminName);
    }


}

